package com.dataextend.config.shiro;

import com.dataextend.config.jwt.JwtToken;
import com.dataextend.config.jwt.JwtUtil;
import com.dataextend.entity.PermissionEntity;
import com.dataextend.entity.RolePermissionEntity;
import com.dataextend.entity.UserEntity;
import com.dataextend.entity.UserRoleEntity;
import com.dataextend.service.*;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
public class ShiroRealm extends AuthorizingRealm {
    @Autowired
    private UserService userService;
    @Autowired
    private UserRoleService userRoleService;
    @Autowired
    private RolePermissionService rolePermissionService;
    @Autowired
    private PermissionService permissionService;
    @Autowired
    private RoleService roleService;


    /**
     * 必须重写此方法，不然Shiro会报错
     */
    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof JwtToken;
    }

    /**
     * 只有当需要检测用户权限的时候才会调用此方法，例如checkRole,checkPermission之类的
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        String username = JwtUtil.getUsername(principals.toString());

        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();

        UserEntity userEntity = userService.queryByUser(username);

        // 判断用户是否有效， 0有效 1无效
        if (userEntity.getStatus().equals(1)) { return simpleAuthorizationInfo; }

        /*
         * 根据用户 id 去查询角色集
         * */
        List<UserRoleEntity> listUserRole = userRoleService.list(new UserRoleEntity().setUserId(userEntity.getId()));

        for (UserRoleEntity uR: listUserRole) {

            // 判断角色是否有效， 0有效 1无效
            if (roleService.queryById(uR.getRoleId()).getStatus().equals(1)) { return simpleAuthorizationInfo; }

            /*
             * 根据角色id去查询角色权限集
             * */
            for (RolePermissionEntity rP: rolePermissionService.list(new RolePermissionEntity().setRoleId(uR.getRoleId()))) {
                /*
                 * 根据权限 id 查询到角色信息
                 * 添加到 shiro 权限集中去
                 * */
                for (PermissionEntity p: permissionService.list(new PermissionEntity().setId(rP.getPermissionId()))) {
                    System.out.println(">>>>>>>>>权限 id:" + p.getUrl());
                    simpleAuthorizationInfo.addStringPermission(p.getUrl());
                }
            }
            /*
             * 获取角色 id
             * 根据角色 id 去 role表查询角色名字
             * 添加到 shiro 角色中去
             * */
            simpleAuthorizationInfo.addRole(roleService.queryById(uR.getRoleId()).getMemo());
        }

        return simpleAuthorizationInfo;
    }

    /**
     * 默认使用此方法进行用户名正确与否验证，错误抛出异常即可。
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken auth) throws AuthenticationException {
        String token = (String) auth.getCredentials();
        // 解密获得username，用于和数据库进行对比
        String username = JwtUtil.getUsername(token);
        if (username == null) {
            throw new AuthenticationException("token无效");
        }

        /*
         * 通过用户名到数据库查询用户信息
         * */
        UserEntity userEntity = userService.queryByUser(username);
        if (userEntity == null) {
            throw new AuthenticationException("用户不存在!");
        }

        if (!JwtUtil.verify(token, username, userEntity.getPassword())) {
            throw new AuthenticationException("用户名或密码错误");
        }

        return new SimpleAuthenticationInfo(token, token, "shiro_realm");
    }
}
